﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using thinger.DataConvertLib;
using thinger.VisionModels;
using thinger.VisitionDAL;

namespace thinger.VisionDemo
{

    public class ZmotionEx : Zmotion
    {
        //板卡初始信号设置

        public string IPAddress = "10.21.0.13";

        //轴号设置
        public short XAxis = 1;//产品旋转轴  1,0；1，1
        public short YAxis = 0;//产品前后移动轴 0,0；0，1

        public short Z1Axis = 2;//左工位左右移动轴  2,0；2，1
        public short U1Axis = 3;//左工位上下移动轴  3，0；3，1
        public short Z2Axis = 4;//右工位左右移动轴  4，0；4,1
        public short U2Axis = 5;//右工位上下移动轴  5,0；5,1

        //左右螺丝刀头485控制旋转

        //运动速度
        public float XMoveVel = 10.0f;
        public float YMoveVel = 10.0f;
        public float Z1MoveVel = 50.0f;
        public float U1MoveVel = 30.0f;
        public float Z2MoveVel = 10.0f;
        public float U2MoveVel = 10.0f;

        //输入信号
        public short XLimitNeg = 192;
        public short XLimitPos = 193;

        public short YLimitNeg =13;
        public short YLimitPos =209;

        public short Z1LimitPos = 0;
        public short Z1LimitNeg = 1;

        public short U1LimitPos = 2;
        public short U1LimitNeg = 3;

        public short Z2LimitPos = 9;
        public short Z2LimitNeg = 8;

        public short U2LimitPos = 7;
        public short U2LimitNeg = 5;//原点信号

        //输出信号  0- 空 1-左吸气  2-左气缸上下 3-右气缸上下 4-吸气  5-顶紧气缸 6-左上顶气缸  7--右上顶气缸
        public short Z1Clip = 1;//空
        public short Z2Clip = 4; //左吸气  
        public short LightLOut =0; //左光源输出  
        public short LightROut = 10;//右光源输出       
        public short ScrewLDownOut = 2;//左螺丝刀下降       
        public short ScrewRDownOut =3;//右螺丝刀下降
        public short ProductClampOut =5;//产品夹紧
        public short ProductUPLOut =6;//产品左顶升
        public short ProductUPROut =7;//产品右顶升

        //位置读取
        RecipeEntity recipeEntity { get; set; }

        #region 初始化板卡
        /// <summary>
        /// 初始化板卡
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isRom"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public OperateResult InitCard(string fileName, bool isRom, int timeOut = 10000)
        {
            //下载BAS文件
            var result = BasDown(fileName, isRom);

            if (result.IsSuccess)
            {
                IEC_Timer_TON ton = new IEC_Timer_TON(timeOut);
                ton.Input = true;

                int initStatus = -1;

                while (true)
                {
                    initStatus = GetInitStatus();

                    bool completed = initStatus >= 1;

                    bool output = ton.Output;

                    if (completed)
                    {
                        break;
                    }
                    else if (!output)
                    {
                        continue;
                    }
                    else
                    {
                        return OperateResult.CreateFailResult("获取初始化状态超时！");
                    }
                }

                switch (initStatus)
                {
                    //正常结束
                    case 1:
                        return new OperateResult(true, "检测到轴数：" + GetTotalAxisnum());
                    case 2:
                        return OperateResult.CreateFailResult("总线扫描失败");
                    case 3:
                        return OperateResult.CreateFailResult("总线启动失败");
                    default:
                        return OperateResult.CreateFailResult("未知错误原因");
                }
            }
            else
            {
                return result;
            }
        }

        #endregion

        #region 回原点

        public OperateResult ZeroU1()
        {
            //return ZeroPos(U1Axis);
            var result = DirectZeroAxis(U1Axis, U1MoveVel, U1MoveVel * 0.1f, U1LimitNeg, 0.0f, U1MoveVel * 10, U1MoveVel * 10);

            if (result.IsSuccess)
            {
                return WaitHomeStop(U1Axis);

            }
            return result;
        }

        public OperateResult ZeroU2()
        {
            //return ZeroPos(U2Axis);
            U2MoveVel = U1MoveVel;
          var result = DirectZeroAxis(U2Axis, U2MoveVel, U2MoveVel * 0.1f, U2LimitNeg, 0.0f, U2MoveVel * 10, U2MoveVel * 10);

            if (result.IsSuccess)
            {
                return WaitHomeStop(U2Axis);
            }
            return result;
        }

        public OperateResult ZeroZ1()
        {
            var result = DirectZeroAxis(Z1Axis, Z1MoveVel, Z1MoveVel * 0.1f, Z1LimitNeg, 0.0f, Z1MoveVel * 10, Z1MoveVel * 10);

            if (result.IsSuccess)
            {
                return WaitHomeStop(Z1Axis);
            }
            return result;
        }

        public OperateResult ZeroZ2()
        {
            Z2MoveVel = Z1MoveVel;
            var result = DirectZeroAxis(Z2Axis, Z2MoveVel, Z2MoveVel * 0.1f, Z2LimitNeg, 0.0f, Z2MoveVel * 10, Z2MoveVel * 10);

            if (result.IsSuccess)
            {
                return WaitHomeStop(Z2Axis);
            }
            return result;
        }

        public OperateResult ZeroX()
        {
            //var result = BUSZeroAxis(XAxis, XMoveVel, XMoveVel * 0.1f, 0.0f, 17);

            //if (result.IsSuccess)
            //{
            //    return WaitBusHomeStop(XAxis);
            //}
            //return result;

            var result = DirectZeroAxis(XAxis, XMoveVel, XMoveVel * 0.1f, XLimitNeg, 0.0f, XMoveVel * 10, XMoveVel * 10);

            if (result.IsSuccess)
            {
                return WaitHomeStop(XAxis);
            }
            return result;
        }


        public OperateResult ZeroY()
        {
            //var result = BUSZeroAxis(YAxis, YMoveVel, YMoveVel * 0.1f, 0.0f, 17);

            //if (result.IsSuccess)
            //{
            //    return WaitBusHomeStop(YAxis);
            //}
            //return result;
            float yValue = 300.0f;
            var result = MoveRelY(yValue);
            if (result.IsSuccess)
            {
                result = DirectZeroAxis(YAxis, YMoveVel, YMoveVel * 0.1f, YLimitNeg, 0.0f, YMoveVel * 10, YMoveVel * 10);

                if (result.IsSuccess)
                {
                    return WaitHomeStop(YAxis);
                }
            }
            return result;


        }

        public OperateResult ZeroAll()
        {
            List<Task<OperateResult>> tasks = new List<Task<OperateResult>>();

            tasks.Add(Task.Run(() =>
            {
                if (ZeroZ1().IsSuccess)
                {
                    return ZeroU1();
                }
                else
                {
                    return OperateResult.CreateFailResult();
                }
            }));

            tasks.Add(Task.Run(() =>
            {
                if (ZeroZ2().IsSuccess)
                {
                    return ZeroU2();
                }
                else
                {
                    return OperateResult.CreateFailResult();
                }
            }));

            var result = Task.WhenAll(tasks).GetAwaiter().GetResult();

            //如果任意一个有问题，就直接返回
            foreach (var item in result)
            {
                if (item.IsSuccess == false)
                {
                    return item;
                }
            }

            tasks = new List<Task<OperateResult>>();

            tasks.Add(Task.Run(() =>
            {
                return ZeroX();
            }));

            tasks.Add(Task.Run(() =>
            {
                return ZeroY();
            }));

            result = Task.WhenAll(tasks).GetAwaiter().GetResult();

            //如果任意一个有问题，就直接返回
            foreach (var item in result)
            {
                if (item.IsSuccess == false)
                {
                    return item;
                }
            }

            return OperateResult.CreateSuccessResult();
        }

        #endregion

        #region 移动封装
        #region  产品前后和旋转运动
        /// <summary>
        /// x,y轴移动封装  产品前后和旋转运动
        /// </summary>
        /// <param name="x">前后 0</param>
        /// <param name="y">旋转 1</param>
        /// <returns></returns>
        public OperateResult MoveX(float x)
        {
            return MoveAbs(XAxis, XMoveVel, x, 0.0f, XMoveVel * 10, XMoveVel * 10, 100);
        }
        public OperateResult MoveY(float y)
        {
            return MoveAbs(YAxis, YMoveVel, y, 0.0f, YMoveVel * 10, YMoveVel * 10, 100);
        }

        /// <summary>
        /// Y相对运动
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        public OperateResult MoveRelY(float y)
        {
            return MoveRelative(YAxis, YMoveVel, y, 0.0f, YMoveVel * 10, YMoveVel * 10, 100);
        }

        public OperateResult MoveXY(float x, float y)
        {
            return MoveLineAbs(new int[] { XAxis, YAxis }, new float[] { x, y }, XMoveVel, XMoveVel * 10, XMoveVel * 10);
        }

        public OperateResult MoveXYRelative(float x, float y)
        {
            return MoveLineRelative(new int[] { XAxis, YAxis }, new float[] { x, y }, XMoveVel, XMoveVel * 10, XMoveVel * 10);
        }
        #endregion

        #region 左螺丝工位左右移动和上下移动控制
        /// <summary>
        /// 左螺丝工位左右移动和上下移动
        /// </summary>
        /// <param name="u1">上下移动</param>
        /// <param name="z1">左右移动</param>
        /// <returns></returns>
        public OperateResult MoveU1(float u1)
        {
            return MoveAbs(U1Axis, U1MoveVel, u1, 0.0f, U1MoveVel * 10, U1MoveVel * 10, 100);
        }

        public OperateResult MoveZ1(float z1)
        {
            return MoveAbs(Z1Axis, Z1MoveVel, z1, 0.0f, Z1MoveVel * 10, Z1MoveVel * 10, 100);
        }

        public OperateResult MoveU1Z1(float u1, float z1)
        {
            return MoveLineAbs(new int[] { U1Axis, Z1Axis }, new float[] { u1, z1 }, U1MoveVel, U1MoveVel * 10, U1MoveVel * 10);
        }

        public OperateResult MoveU1Z1Relative(float u1, float z1)
        {
            return MoveLineRelative(new int[] { U1Axis, Z1Axis }, new float[] { u1, z1 }, U1MoveVel, U1MoveVel * 10, U1MoveVel * 10);
        }

        #region 右螺丝工位左右移动和上下移动控制
        /// <summary>
        /// 左螺丝工位左右移动和上下移动
        /// </summary>
        /// <param name="u2">上下移动</param>
        /// <param name="z2">左右移动</param>
        /// <returns></returns>
        public OperateResult MoveU2(float u2)
        {
            U2MoveVel = U1MoveVel;
            return MoveAbs(U2Axis, U2MoveVel, u2, 0.0f, U2MoveVel * 10, U2MoveVel * 10, 100);
        }

        public OperateResult MoveZ2(float z2)
        {
            Z2MoveVel = Z1MoveVel;
            return MoveAbs(Z2Axis, Z2MoveVel, z2, 0.0f, Z2MoveVel * 10, Z2MoveVel * 10, 100);
        }

        public OperateResult MoveU2Z2(float u2, float z2)
        {

            return MoveLineAbs(new int[] { U2Axis, Z2Axis }, new float[] { u2, z2 }, U2MoveVel, U2MoveVel * 10, U2MoveVel * 10);
        }

        public OperateResult MoveU2Z2Relative(float u2, float z2)
        {
            return MoveLineRelative(new int[] { U2Axis, Z2Axis }, new float[] { u2, z2 }, U2MoveVel, U2MoveVel * 10, U2MoveVel * 10);
        }
        #endregion
        #endregion

        #endregion

        #region 气源电磁阀控制

        /// <summary>
        /// Z1电磁阀
        /// </summary>
        /// <returns></returns>
        public bool Z1ClipState()
        {
            return GetOutput(Z1Clip);
        }

        public OperateResult Z1ClipOpen()
        {
            return SetOutput(Z1Clip, true);
        }
        public OperateResult Z1ClipClose()
        {
            return SetOutput(Z1Clip, false);
        }
        public bool Z2ClipState()
        {
            return GetOutput(Z2Clip);
        }

        public OperateResult Z2ClipOpen()
        {
            return SetOutput(Z2Clip, true);
        }
        public OperateResult Z2ClipClose()
        {
            return SetOutput(Z2Clip, false);
        }
        /// <summary>
        /// 读取左螺丝下压气缸状态
        /// </summary>
        /// <returns></returns>
        public bool GetScrewLDownOutState()
        {
            return GetOutput(ScrewLDownOut);
        }

        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ScrewLDownOutOpen()
        {
            return SetOutput(ScrewLDownOut, true);
        }

        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ScrewLDownOutClose()
        {
            return SetOutput(ScrewLDownOut, false);
        }

        /// <summary>
        /// 读取右螺丝下压气缸状态
        /// </summary>
        /// <returns></returns>
        public bool GetScrewRDownOutState()
        {
            return GetOutput(ScrewRDownOut);
        }
        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ScrewRDownOutOpen()
        {
            return SetOutput(ScrewRDownOut, true);
        }

        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ScrewRDownOutClose()
        {
            return SetOutput(ScrewRDownOut, false);
        }

        /// <summary>
        /// 读取产品夹紧气缸状态
        /// </summary>
        /// <returns></returns>
        public bool GetProductClampOutState()
        {
            return GetOutput(ProductClampOut);
        }
        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ProductClampOutOpen()
        {
            return SetOutput(ProductClampOut, true);
        }

        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ProductClampOutClose()
        {
            return SetOutput(ProductClampOut, false);
        }

        /// <summary>
        /// 读取产品左顶升气缸状态
        /// </summary>
        /// <returns></returns>
        public bool GetProductUPLOutState()
        {
            return GetOutput(ProductUPLOut);
        }
        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ProductUPLOutOpen()
        {
            return SetOutput(ProductUPLOut, true);
        }

        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ProductUPLOutClose()
        {
            return SetOutput(ProductUPLOut, false);
        }

        /// <summary>
        /// 读取产品右顶升气缸状态
        /// </summary>
        /// <returns></returns>
        public bool GetProductUPROutState()
        {
            return GetOutput(ProductUPROut);
        }
        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ProductUPROutOpen()
        {
            return SetOutput(ProductUPROut, true);
        }

        /// <summary>
        /// 左螺丝气缸下压
        /// </summary>
        /// <returns></returns>
        public OperateResult ProductUPROutClose()
        {
            return SetOutput(ProductUPROut, false);
        }
        #endregion

        #region 光源控制
        /// <summary>
        /// 读取左光源的状态
        /// </summary>
        /// <returns></returns>
        public bool GetLightLState()
        {
            return GetOutput(LightLOut);
        }

        /// <summary>
        /// 打开左光源
        /// </summary>
        /// <returns></returns>
        public OperateResult LightLOpen()
        {
            return SetOutput(LightLOut, true);
        }

        /// <summary>
        /// 关闭左光源
        /// </summary>
        /// <returns></returns>
        public OperateResult LightLClose()
        {
            return SetOutput(LightLOut, false);
        }


        /// <summary>
        /// 读取右光源状态
        /// </summary>
        /// <returns></returns>
        public bool GetLightRState()
        {
            return GetOutput(LightROut);
        }

        /// <summary>
        /// 打开右光源
        /// </summary>
        /// <returns></returns>
        public OperateResult LightROpen()
        {
            return SetOutput(LightROut, true);
        }

        /// <summary>
        /// 关闭右光源
        /// </summary>
        /// <returns></returns>
        public OperateResult LightRClose()
        {
            return SetOutput(LightROut, false);
        }



        #endregion

        #region 伺服使能

        public bool GetXAxisEnable()
        {
            return GetEnable(XAxis);
        }

        public bool GetYAxisEnable()
        {
            return GetEnable(YAxis);
        }

        public OperateResult SetXAxisEnable(bool enable)
        {
            return SetEnable(XAxis, enable);
        }

        public OperateResult SetYAxisEnable(bool enable)
        {
            return SetEnable(YAxis, enable);
        }

        #endregion

        #region  获取限位信号
        public bool GetXLimitPos()
        {
            return GetInput(XLimitPos);
        }

        public bool GetXLimitNeg()
        {
            return GetInput(XLimitNeg);
        }

        public bool GetYLimitPos()
        {
            return GetInput(YLimitPos);
        }

        public bool GetYLimitNeg()
        {
            return GetInput(YLimitNeg);
        }

        public bool GetZ1LimitPos()
        {
            return GetInput(Z1LimitPos);
        }

        public bool GetZ1LimitNeg()
        {
            return GetInput(Z1LimitNeg);
        }

        public bool GetZ2LimitPos()
        {
            return GetInput(Z2LimitPos);
        }

        public bool GetZ2LimitNeg()
        {
            return GetInput(Z2LimitNeg);
        }

        #endregion

        #region 获取实时位置

        public string GetXPos()
        {
            //return "产品前后：" + GetPos(XAxis).ToString("f2") + " mm";
            return  GetPos(XAxis).ToString("f2");
        }

        public string GetYPos()
        {
            //return "产品旋转：" + GetPos(YAxis).ToString("f2") + " °";
            return  GetPos(YAxis).ToString("f2");
        }
        public string GetZ1Pos()
        {
            //return "左工位左右轴：" + GetPos(Z1Axis).ToString("f2") + " mm";
            return  GetPos(Z1Axis).ToString("f2") ;
        }

        public string GetU1Pos()
        {
            //return "左工位上下轴：" + GetPos(U1Axis).ToString("f2") + " mm";
            return GetPos(U1Axis).ToString("f2") ;
        }
        public string GetZ2Pos()
        {
            //return "右工位左右轴：" + GetPos(Z2Axis).ToString("f2") + " mm";
            return  GetPos(Z2Axis).ToString("f2");
        }

        public string GetU2Pos()
        {
            //return "右工位上下轴：" + GetPos(U2Axis).ToString("f2") + " mm";
            return GetPos(U2Axis).ToString("f2");
        }

        #endregion

    }
}
